iT邦幫忙

2022 iThome 鐵人賽

DAY 6
0
自我挑戰組

30天 Ruby on Rails 挑戰系列 第 6

Rails 30天挑戰第六天 CRUD(四)

  • 分享至 

  • xImage
  •  

edit/update

先在index.html.erb加上編輯的連結

<h1>Hello World!!</h1>
<%= link_to "新增",new_book_path %>
<% @books.each do |book|%>

  <%= link_to book.title,book_path %>
  <%= link_to "編輯",edit_book_path(book) %>

<% end%>
```html
edit_book_path後面加上(book),讓他找得到book的id。

回到controller寫edit的action
```ruby
  def edit
    @book = Book.find(params[:id])
  end

有沒有覺得很熟悉,沒錯直接複製show的就好了,他們都是去找特定id的頁面。
再來寫update的action,一樣也是複製貼上,這次複製create的內容,再一點點修改。

  def update
    @book = Book.find(params[:id])
    if @book.update(book_params)
      redirect_to books_path
    else
      render :edit
    end
  end

update的資料要先清洗過,render換成edit頁面。

再來寫view,建立edit.html.erb

<h1>編輯</h1>
<%= form_with model:@book do |form| %>
  <div>標題:<%=form.text_field :title %></div>
  <div>內容:<%=form.text_area :content %></div>
  <div>價錢:<%=form.text_field :price %></div>
  <%= form.submit "編輯商品"%>
<% end %>

有沒有覺得很眼熟,沒錯,跟new的view一樣,複製貼上換上編輯看個字而已。
這兩個的code重複使用的時候,可以建立一個檔案,讓他們去render。
建立_form.html.erb。名字可隨意取,但是最前面要加上_

  <%= form_with model:book do |form| %>
  <div>標題:<%=form.text_field :title %></div>
  <div>內容:<%=form.text_area :content %></div>
  <div>價錢:<%=form.text_field :price %></div>
  <%= form.submit %>
<% end %>

注意的兩點,把實體變數變成一般的變數,@book => book 。
再來是submit的內容因為略有不同,所以刪掉讓submit自動生字。

這時候的new.html.erb/edit.html.erb

<h1>新增</h1>

<%= render "form", book: @book %>
<h1>編輯</h1>

<%= render "form", book: @book %>

render _form.html.erb的內容,然後將變數book指定成@book。

destroy

先在index的view寫上刪除的連結

<h1>Hello World!!</h1>
<%= link_to "新增",new_book_path %>
<% @books.each do |book|%>

  <%= link_to book.title,book_path %>
  <%= link_to "編輯",edit_book_path(book) %>
  <%= link_to "刪除",book_path  %>
<% end%>

當你點擊刪除的時候,你會發現你的網頁會跑向show的頁面。

rails routes明明寫著Perfix也是book。

在這裡show/update/destroy都是共用book_path,我們要再後面加上method,來區分它們。

<h1>Hello World!!</h1>
<%= link_to "新增",new_book_path %>
<% @books.each do |book|%>

  <%= link_to book.title,book_path %>
  <%= link_to "編輯",edit_book_path(book) %>
  <%= link_to "刪除",book_path,method: "delete"  %>
<% end%>

為了避免使用者按了就直接刪除,給他加一個警告確認
book_path可以簡寫成book

<h1>Hello World!!</h1>
<%= link_to "新增",new_book_path %>
<% @books.each do |book|%>

  <%= link_to book.title,book %>
  <%= link_to "編輯",edit_book_path(book) %>
  <%= link_to "刪除",book,method: "delete" ,data: {confirm: "是否刪除?"}  %>
<% end%>


按下去後看到眼熟的紅色框框,Unknown action,代表我們做對方向了,補上destroy action

class BooksController < ApplicationController
    
  def destroy
    @book = Book.find(params[:id])
    @book.destroy
    redirect_to books_path
  end
    
end

這樣刪除就完成了,到這邊CRUD的功能已經具備,但是如果仔細一看,會發現@book = Book.find(params[:id])這行code一直不斷重複使用。

當你相同的東西一直重複使用的時候,就應該把他寫成一個方法,讓大家都能使用。

private

def find_book
  @book = Book.find(params[:id])
end

但是如果只是這樣還不夠,難道我們要一直重複呼喚這個方法。
在Rails有一個寫法叫做before_action,他會讓方法直接默認的在action裡使用過,不用在多個action一直重複寫這方法。

before_action放在最上面,要在action之前執行

class BooksController < ApplicationController
  before_action :find_book,only: [:show, :edit, :update, :destroy]
  
  def index
    @books = Book.order(id: :desc)
  end
  .
  .
  .
end        

before_action有兩種寫法,only是只有這些action執行方法,另一個except則是除了這些action以外通通都要執行。

[:show, :edit, :update, :destroy]這四個action的@book = Book.find(params[:id])就可以刪掉了。


上一篇
Rails 30天挑戰第五天 CRUD(三)
系列文
30天 Ruby on Rails 挑戰6
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言